package com.study.springboot.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.study.springboot.common.constant.RedisConst;
import com.study.springboot.common.constant.StatusEnum;
import com.study.springboot.common.util.RedisUtil;
import com.study.springboot.mapper.StudentMapper;
import com.study.springboot.model.entity.Student;
import com.study.springboot.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Admin
 * @since 2021-11-21
 */
@Slf4j
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    @Autowired
    RedisUtil redisUtil;

    @CacheEvict(value = RedisConst.PREFIX, allEntries = true) //所有以value开头的缓存都会被清除
    @Transactional
    @Override
    public void add(Student student) {
        baseMapper.insert(student);
    }

    @Cacheable(value = RedisConst.PREFIX, key = "'student:'+#id")
    @Override
    public Student queryById(Long id) {
        return this.getById(id);
    }

    //使用双重检查锁解决热点缓存问题
    @Override
    public Integer queryCount() {
        //从缓存中读取数据
        Integer count = redisUtil.getObject(RedisConst.STUDENT_COUNT, Integer.class);
        if (null == count) {
            synchronized (this) {
                if (null == redisUtil.getObject(RedisConst.STUDENT_COUNT, Integer.class)) {
                    //从数据库中查询数据
                    count = baseMapper.selectCount(Wrappers.<Student>lambdaQuery()
                            .eq(Student::getDeleteStatus, StatusEnum.NO.getCode()));
                    //将数据写入缓存并设置到期时间
                    redisUtil.setObject(RedisConst.STUDENT_COUNT, count, 10, TimeUnit.MINUTES);
                }
            }
        }
        return count;
    }

}
